﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using DomainDriver.CommonUtilities.Reflectors;
using DomainDriver.DomainModeling.Constraints;
using DomainDriver.DomainModeling.DataProviders;
using DomainDriver.DomainModeling.Queries;
using DomainDriver.DomainModeling.Repositories;
using DomainDriver.DomainModeling.Example;
using DomainDriver.DomainModeling.Example.DomainObjects;
using DomainDriver.DomainModeling.GenericUnitTesting.Repositories;

namespace DomainDriver.DomainModeling.UnitTests.Repositories
{
    [TestFixture(new object[] { DataSourcePersistenceType.None })]
    [TestFixture(new object[] { DataSourcePersistenceType.File })]
    [TestFixture(new object[] { DataSourcePersistenceType.Database })]
    public class DummyDomainObjectRepositoryTests : RepositoryTestFixture<ExampleDomainModel, Guid, DummyDomainObject>
    {
        protected Guid m_Child1Id = Guid.NewGuid();
        protected Guid m_Child2Id = Guid.NewGuid();
        protected Guid m_Child3Id = Guid.NewGuid();

        public DummyDomainObjectRepositoryTests(DataSourcePersistenceType persistenceType)
            : base(persistenceType)
        {
            // do nothing
        }

        protected override ExampleDomainModel CreateDomainModel(DataSourcePersistenceType persistenceType, bool buildModelWithConstraints)
        {
            ExampleDomainModel model = new ExampleDomainModel(persistenceType, buildModelWithConstraints);
            return model;
        }

        protected override DummyDomainObject CreateDomainObject()
        {
            DummyDomainObject domainObject = new DummyDomainObject();
            domainObject.Name = domainObject.Key.ToString();

            domainObject.AddChild(m_Child1Id);
            domainObject.AddChild(m_Child2Id);

            return domainObject;
        }

        protected override void UpdateDomainObject(DummyDomainObject domainObject, ref bool objectCanBeUpdated)
        {
            objectCanBeUpdated = true;
            domainObject.Name = domainObject.Key.ToString() + "U";

            domainObject.RemoveChild(m_Child2Id);
            domainObject.AddChild(m_Child3Id);
        }

        [Test]
        public virtual void VerifyTypeSpecificQueryUsage()
        {
            IRepository<Guid, DummyDomainObject> repository = DomainModel.GetRepository<Guid, DummyDomainObject>();

            DummyDomainObject childDomainObject = new DummyDomainObject();
            childDomainObject.Name = "Child";
            repository.Add(childDomainObject);

            DummyDomainObject parentDomainObject = new DummyDomainObject();
            parentDomainObject.Name = "Parent";
            parentDomainObject.AddChild(childDomainObject.Key);
            repository.Add(parentDomainObject);

            string namePropertyName = ClassReflector.GetPropertyName((DummyDomainObject testObject) => testObject.Name);
            EqualsQuery<DummyDomainObject> nameQuery = new EqualsQuery<DummyDomainObject>(namePropertyName, "Child");
            ICollection<DummyDomainObject> matchingObjects = repository.Read(nameQuery);

            Assert.AreEqual(1, matchingObjects.Count);

            string childrenPropertyName = ClassReflector.GetPropertyName((DummyDomainObject testObject) => testObject.Children);
            ContainsQuery<DummyDomainObject> childIdQuery = new ContainsQuery<DummyDomainObject>(childrenPropertyName, childDomainObject.Key);
            matchingObjects = repository.Read(childIdQuery);

            Assert.AreEqual(1, matchingObjects.Count);
        }
    }
}